from selenium import webdriver
import gevent
from selenium.webdriver.remote.webdriver import WebDriver, WebElement

from utils.websocket import send_msg_with_date, MsgCommend, send_msg_screenshot
from utils.selenium.highlighted import ElementHighlighted
from utils.selenium.find import FindElement, FindType


class WPerform():
    """
    执行类：贯穿并连接整个操作执行
    """

    def __init__(self, websocket, chrome: str):
        """
        初始化方法
        :param websocket: websocket
        :param use_case_data: 用例数据
        """
        self.driver: WebDriver = None
        self.websocket = websocket
        self.chrome_drive_path = chrome
        self.start_page_path = None

    def create_driver(self):
        self.quit()
        self.driver: WebDriver = webdriver.Chrome(executable_path=self.chrome_drive_path)

    def start(self, interval=2):
        """
        启动方法
        :param interval: 启动后的时间间隔
        """
        self.driver.get(self.start_page_path)
        self.sleep(interval)

    def end(self):
        """
        执行结束 - 不能自己调用（如果调用就会中断执行）
        :return:
        """
        send_msg_with_date(self.websocket, '执行完成', MsgCommend.finish)

    def send_msg(self, msg: str):
        """
        发送信息
        :param msg: 信息
        :return:
        """
        send_msg_with_date(self.websocket, msg, MsgCommend.log)

    def send_json(self, msg: str):
        """
        发送信息
        :param msg: 信息
        :return:
        """
        send_msg_with_date(self.websocket, msg, MsgCommend.json)

    def sleep(self, interval: int):
        """
        延迟方法
        :param interval: 间隔秒
        :return:
        """
        gevent.sleep(interval)

    def send_err(self, msg: str, err_is_pass=False):
        """
        发送错误信息
        :param msg:
        :err_is_pass msg: 错误是否允许通过
        :return:
        """
        if self.driver:
            self.screenshot()
        if err_is_pass:
            send_msg_with_date(self.websocket, msg, MsgCommend.use_case_err)
        else:
            send_msg_with_date(self.websocket, msg, MsgCommend.err)
            raise Exception('失败 => %s' % msg)

    def open_new_page(self, page_path: str):
        """打开新的界面"""
        js = 'window.open("%s");' % page_path
        self.run_js(js)

    def update_page_url(self, page_path: str):
        """切换页面"""
        js = 'location.href = "%s";' % page_path
        self.run_js(js)

    def run_js(self, js: str):
        """执行js"""
        self.driver.execute_script(js)

    def screenshot(self):
        """
        截图
        :return:
        """
        img_path = send_msg_screenshot(self.websocket)
        self.driver.get_screenshot_as_file(img_path)

    def highlighted(self, element: list or WebElement):
        """
        高亮
        :param element: WebElement 或者 list<WebElement>
        :return:
        """
        ElementHighlighted.highlighted(self.driver, element=element)

    def quit(self):
        """退出"""
        try:
            self.driver and self.driver.quit()
            self.driver = None
        except Exception as e:
            print('quit', e)

    def switch_window(self, index: int = None):
        """
        切换窗口
        :param index:
        :return:
        """
        handles = self.driver.window_handles
        if index == None:
            current_window_handle = self.driver.current_window_handle
            index = handles.index(current_window_handle) + 1
        if index > len(handles) - 1 or index < 0:
            raise Exception('窗口未找到 ==> 窗口索引【%d】' % index + 1)
        window_name = handles[index]
        self.driver.switch_to.window(window_name)

    def fint(self, find_type: FindType, find_key: str, multiple=False, highlighted=True, find_index=None, super_element=None, is_filter_hide_element=True) -> WebElement or list:
        """
        查询元素
        :param find_type: 查询类型
        :param find_key: 查询KEY
        :param multiple: 是否查询多个
        :param highlighted: 是否高亮
        :param find_index: 查询多个的索引（如果执行就查询指定的单个数据）
        :return: 如果查到返回，没查到返回空数据
        :param super_element: 父元素
        :param is_filter_hide_element 是否过滤掉隐藏的
        """
        return FindElement.find_element(super_element or self.driver, find_type, find_key, multiple, highlighted, find_index, is_filter_hide_element=is_filter_hide_element)